package GestorUsuarios;

/**
 * @file Usuario.java
 * @brief Implementa la clase Usuario
 * 
 * Implementa la clase Usuario usada para manejar la información de
 * los usuarios del sistema.
 * 
 * @author Víctor Martínez Gómez
 * @version 01.02
 * 
 */

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.util.Date;

import GestorClinico.Direccion;
import GestorClinico.DireccionDAO;

/**
 * @class Usuario
 * 
 * @brief Se encarga de realizar las operaciones para manejar la información de
 * 		  los usuarios del sistema.
 * 
 *        Se encarga de realizar las operaciones para manejar la información de
 *		  los usuarios del sistema. Permite crearlos, modificarlos y obtener sus
 *		  datos.
 * 
 */

public class Usuario {
	
	/**
	 * @brief Id del usuario
	 */
	private int _idUsuario;
	/**
	 * @brief Dni o pasaporte del usuario
	 */
	private String _dniPasaporte;
	/**
	 * @brief Nombre del usuario
	 */
	private String _nombre;
	/**
	 * @brief Apellidos del usuario
	 */
	private String _apellidos;
	/**
	 * @brief Fecha nacimiento del usuario
	 */
	private Date _fechaNacimiento;
	/**
	 * @brief Genero del usuario
	 */
	private GeneroUsuario _genero;
	/**
	 * @brief Correo electronico del usuario
	 */
	private String _correo;
	/**
	 * @brief Telefono movil de contacto del usuario
	 */
	private int _telefonoMovil;
	/**
	 * @brief Nombre de login del usuario
	 */
	private String _login;
	/**
	 * @brief Contraseña encriptada en MD5 del usuario
	 */
	private String _password;
	/**
	 * @brief Estado del usuario en el sistema
	 */
	private EstadoUsuario _estado;
	/**
	 * @brief Tipo de usuario en el sistema
	 */
	private TipoUsuario _tipo;

        /**
         * @brief Observaciones clinicas del paciente
         */
        protected String _observaciones;
        
	/**
	 * @brief Constructor de Usuario
	 */
	public Usuario(String dnipasaporte, String nombre,
			String apellidos, Date fechanacimiento, GeneroUsuario genero,
			String correo, int telefonomovil, String login, String password,
			EstadoUsuario estado, TipoUsuario tipo , String observaciones) throws NoSuchAlgorithmException {
		_idUsuario = -1;
		_dniPasaporte = dnipasaporte;
		_nombre = nombre;
		_apellidos = apellidos;
		_fechaNacimiento = fechanacimiento;
		_genero = genero;
		_correo = correo;
		_telefonoMovil = telefonomovil;
		_login = login;
		_password = password;
		_estado = estado;
		_tipo = tipo;
                _observaciones = observaciones;
	}
	
	/**
	 * @brief Constructor de Usuario
	 */
	public Usuario(int idusuario, String dnipasaporte, String nombre,
			String apellidos, Date fechanacimiento, GeneroUsuario genero,
			String correo, int telefonomovil, String login, String password,
			EstadoUsuario estado, TipoUsuario tipo, String observaciones)
                        throws NoSuchAlgorithmException {
		_idUsuario = idusuario;
		_dniPasaporte = dnipasaporte;
		_nombre = nombre;
		_apellidos = apellidos;
		_fechaNacimiento = fechanacimiento;
		_genero = genero;
		_correo = correo;
		_telefonoMovil = telefonomovil;
		_login = login;
		_password = password;
		_estado = estado;
		_tipo = tipo;
                _observaciones = observaciones;
	}

	/**
	 * @brief Constructor usuario
	 */
	public Usuario() {
	}

	/**
	 * @brief Añade el usuario a la base de datos y le asigna el nuevo id
	 * @param usuario El usuario a añadir
	 * @return True si la operación se completó correctamente
	 * @throws ClassNotFoundException, IOException, SQLException, IDException, NoSuchAlgorithmException 
	 */
	public static boolean add(Usuario usuario) throws SQLException, IOException, ClassNotFoundException, IDException, NoSuchAlgorithmException {
		UsuarioDAO.add(usuario);
		return true;
	}
	
	/**
	 * @brief Devuelve un usuario usando su id para buscarlo
	 * @param usuario El usuario a buscar
	 * @return El usuario encontrado o null si no lo encuentra
	 * @throws ClassNotFoundException, IOException, SQLException, NoSuchAlgorithmException 
	 */
	public static Usuario get(int id) throws SQLException, IOException, ClassNotFoundException, NoSuchAlgorithmException {
		Usuario usuario = UsuarioDAO.get(id);
                if(usuario != null){
                    if(usuario.getTipo()==TipoUsuario.PACIENTE)
			return new Paciente(usuario.getIdUsuario(),usuario.getDniPasaporte(),
								usuario.getNombre(),usuario.getApellidos(),
								usuario.getFechaNacimiento(),usuario.getGenero(),
								usuario.getCorreo(),usuario.getTelefonoMovil(),
								usuario.getLogin(),usuario.getPassword(),
								usuario.getEstado(),usuario.getObservaciones());
                    if(usuario.getTipo()==TipoUsuario.GESTOR)
			return new Gestor(usuario.getIdUsuario(),usuario.getDniPasaporte(),
					usuario.getNombre(),usuario.getApellidos(),
					usuario.getFechaNacimiento(),usuario.getGenero(),
					usuario.getCorreo(),usuario.getTelefonoMovil(),
					usuario.getLogin(),usuario.getPassword(),
					usuario.getEstado(),null);
                    if(usuario.getTipo()==TipoUsuario.FARMACEUTICO)
			return new Farmaceutico(usuario.getIdUsuario(),usuario.getDniPasaporte(),
					usuario.getNombre(),usuario.getApellidos(),
					usuario.getFechaNacimiento(),usuario.getGenero(),
					usuario.getCorreo(),usuario.getTelefonoMovil(),
					usuario.getLogin(),usuario.getPassword(),
					usuario.getEstado(),null);
                    if(usuario.getTipo()==TipoUsuario.MEDICO)
			return new Medico(usuario.getIdUsuario(),usuario.getDniPasaporte(),
					usuario.getNombre(),usuario.getApellidos(),
					usuario.getFechaNacimiento(),usuario.getGenero(),
					usuario.getCorreo(),usuario.getTelefonoMovil(),
					usuario.getLogin(),usuario.getPassword(),
					usuario.getEstado(),null);
                    if(usuario.getTipo()==TipoUsuario.TECNICOPRUEBAS)
			return new TecnicoPruebas(usuario.getIdUsuario(),usuario.getDniPasaporte(),
					usuario.getNombre(),usuario.getApellidos(),
					usuario.getFechaNacimiento(),usuario.getGenero(),
					usuario.getCorreo(),usuario.getTelefonoMovil(),
					usuario.getLogin(),usuario.getPassword(),
					usuario.getEstado(),null);
                }
		return null;
	}
	
	/**
	 * @brief Devuelve un usuario buscando por diversos parametros. Utiliza polimorfimo para devolver el tipo adecuado
	 * @return Vector de usuarios encontrados
	 * @throws ClassNotFoundException, IOException, SQLException, NoSuchAlgorithmException 
	 */
	public static Usuario[] get(String dniPasaporte, String login, String nombre, String apellidos, TipoUsuario tipousuario, EstadoUsuario estado) throws SQLException, IOException, ClassNotFoundException, NoSuchAlgorithmException {
		Usuario [] usuarios = UsuarioDAO.get(dniPasaporte,login,nombre,apellidos,tipousuario,estado);
		if(usuarios==null)
			return null;
                
		for(int i=0;i<usuarios.length;i++) {
			if(usuarios[i].getTipo()==TipoUsuario.PACIENTE)
				usuarios[i] =  new Paciente(usuarios[i].getIdUsuario(),usuarios[i].getDniPasaporte(),
						usuarios[i].getNombre(),usuarios[i].getApellidos(),
						usuarios[i].getFechaNacimiento(),usuarios[i].getGenero(),
						usuarios[i].getCorreo(),usuarios[i].getTelefonoMovil(),
						usuarios[i].getLogin(),usuarios[i].getPassword(),
						usuarios[i].getEstado(),usuarios[i].getObservaciones());
			if(usuarios[i].getTipo()==TipoUsuario.GESTOR)
				usuarios[i] =  new Gestor(usuarios[i].getIdUsuario(),usuarios[i].getDniPasaporte(),
						usuarios[i].getNombre(),usuarios[i].getApellidos(),
						usuarios[i].getFechaNacimiento(),usuarios[i].getGenero(),
						usuarios[i].getCorreo(),usuarios[i].getTelefonoMovil(),
						usuarios[i].getLogin(),usuarios[i].getPassword(),
						usuarios[i].getEstado(),null);
			if(usuarios[i].getTipo()==TipoUsuario.FARMACEUTICO)
				usuarios[i] =  new Farmaceutico(usuarios[i].getIdUsuario(),usuarios[i].getDniPasaporte(),
						usuarios[i].getNombre(),usuarios[i].getApellidos(),
						usuarios[i].getFechaNacimiento(),usuarios[i].getGenero(),
						usuarios[i].getCorreo(),usuarios[i].getTelefonoMovil(),
						usuarios[i].getLogin(),usuarios[i].getPassword(),
						usuarios[i].getEstado(),null);
			else if(usuarios[i].getTipo()==TipoUsuario.MEDICO)
				usuarios[i] =  new Medico(usuarios[i].getIdUsuario(),usuarios[i].getDniPasaporte(),
						usuarios[i].getNombre(),usuarios[i].getApellidos(),
						usuarios[i].getFechaNacimiento(),usuarios[i].getGenero(),
						usuarios[i].getCorreo(),usuarios[i].getTelefonoMovil(),
						usuarios[i].getLogin(),usuarios[i].getPassword(),
						usuarios[i].getEstado(),null);
                        else if(usuarios[i].getTipo()==TipoUsuario.TECNICOPRUEBAS)
				usuarios[i] =  new TecnicoPruebas(usuarios[i].getIdUsuario(),usuarios[i].getDniPasaporte(),
						usuarios[i].getNombre(),usuarios[i].getApellidos(),
						usuarios[i].getFechaNacimiento(),usuarios[i].getGenero(),
						usuarios[i].getCorreo(),usuarios[i].getTelefonoMovil(),
						usuarios[i].getLogin(),usuarios[i].getPassword(),
						usuarios[i].getEstado(),null);
		}
		return usuarios;
	}

	/**
	 * @brief Actualiza un usuario en la base de datos
	 * @param usuario El usuario a actualizar
	 * @throws ClassNotFoundException, IOException, SQLException 
	 */
	public static boolean update(Usuario usuario) throws SQLException, IOException, ClassNotFoundException {
		UsuarioDAO.update(usuario);
		return true;
	}
	
	/**
	 * @brief Obtiene una lista de bitacoras asociadas al usuario
	 * @param fecha Fecha en la que buscar la bitacora
	 * @return Vector de bitacoras encontradas
	 * @throws IDException, ClassNotFoundException, IOException, SQLException, NoSuchAlgorithmException 
	 */
	public Bitacora [] getBitacora(Date fecha) throws NoSuchAlgorithmException, SQLException, IOException, ClassNotFoundException, IDException {
		return BitacoraDAO.get(fecha, null, this.getIdUsuario(), null);
	}
	
	/**
	 * @brief Obtiene la última bitacora del usuario
	 * @param fecha Fecha en la que buscar la bitacora
	 * @return Vector de bitacoras encontradas
	 * @throws IDException, ClassNotFoundException, IOException, SQLException, NoSuchAlgorithmException 
	 */
	public Bitacora getUltimaEntradaBitacora() throws NoSuchAlgorithmException, SQLException, IOException, ClassNotFoundException, IDException {
		return BitacoraDAO.getUltimaEntradaBitacora(this.getIdUsuario());
	}
	
	/**
	 * @brief Obtiene el id del usuario
	 */
	public int getIdUsuario() {
		return _idUsuario;
	}
	
	/**
	 * @brief Establece el id del usuario
	 * @param id Nuevo id del usuario
	 */
	public void setIdUsuario(int id) {
		_idUsuario = id;
	}
	
	/**
	 * @brief Obtiene el DNI o pasaporte del usuario
	 */
	public String getDniPasaporte() {
		return _dniPasaporte;
	}
	
	/**
	 * @brief Establece el DNI o pasaporte del usuario
	 * @param dniopas Nuevo DNI o pasaporte del usuario
	 */
	public void setDniPasaporte(String dniopas) {
		_dniPasaporte = dniopas;
	}
	
	/**
	 * @brief Obtiene el nombre del usuario
	 */
	public String getNombre() {
		return _nombre;
	}
	
	/**
	 * @brief Establece el nombre del usuario
	 * @param nombre Nuevo nombre del usuario
	 */
	public String setNombre(String nombre) {
		return _nombre = nombre;
	}

	/**
	 * @brief Obtiene los apellidos del usuario
	 */
	public String getApellidos() {
		return _apellidos;
	}
	
	/**
	 * @brief Establece los apellidos del usuario
	 * @param apellidos Nuevos apellidos del usuario
	 */
	public void setApellidos(String apellidos) {
		_apellidos = apellidos;
	}
	
	/**
	 * @brief Obtiene la fecha de nacimiento del usuario
	 */
	public Date getFechaNacimiento() {
		return _fechaNacimiento;
	}
	
	/**
	 * @brief Establece la fecha de nacimiento del usuario
	 * @param fecha Nueva fecha de nacimiento
	 */
	public void setFechaNacimiento(Date fecha) {
		_fechaNacimiento = fecha;
	}
	
	/**
	 * @brief Obtiene el genero del usuario
	 */
	public GeneroUsuario getGenero() {
		return _genero;
	}
	
	/**
	 * @brief Establece el genero del usuario
	 * @param genero Nuevo genero del usuario
	 */
	public void setGenero(GeneroUsuario genero) {
		_genero = genero;
	}

	/**
	 * @brief Obtiene el correo del usuario
	 */
	public String getCorreo() {
		return _correo;
	}
	
	/**
	 * @brief Obtiene el correo del usuario
	 * @param correo Nuevo correo del usuario
	 */
	public void setCorreo(String correo) {
		_correo = correo;
	}
	
	/**
	 * @brief Obtiene el telefono movil del usuario
	 */
	public int getTelefonoMovil() {
		return _telefonoMovil;
	}
	
	/**
	 * @brief Obtiene el telefono movil del usuario
	 * @param telefono Nuevo telefono movil del usuario
	 */
	public void setTelefonoMovil(int telefono) {
		_telefonoMovil = telefono;
	}
	
	/**
	 * @brief Obtiene el login del usuario
	 */
	public String getLogin() {
		return _login;
	}
	
	/**
	 * @brief Establece el login del usuario
	 * @param login Nuevo login del usuario
	 */
	public void setLogin(String login) {
		_login = login;
	}
	
	/**
	 * @brief Obtiene el password del usuario encriptado
	 */
	public String getPassword() {
		return _password;
	}
	
	/**
	 * @brief Establece el password del usuario y lo almacena encriptado
	 * @param password Nuevo password del usuario si encriptar
	 * @throws NoSuchAlgorithmException 
	 */
	public void setPassword(String password) throws NoSuchAlgorithmException {
		_password = password;
	}
	
	/**
	 * @brief Obtiene el estado del usuario
	 */
	public EstadoUsuario getEstado() {
		return _estado;
	}
	
	/**
	 * @brief Establece el estado del usuario
	 * @param estado Nuevo estado del usuario
	 */
	public void setEstado(EstadoUsuario estado) {
		_estado = estado;
	}
	
	/**
	 * @brief Obtiene el tipo del usuario
	 */
	public TipoUsuario getTipo() {
		return _tipo;
	}
	
	/**
	 * @brief Establece el tipo del usuario
	 * @param tipo Nuevo tipo del usuario
	 */
	public void setTipo(TipoUsuario tipo) {
		_tipo = tipo;
	}

        /**
         *
         * @return
         */
        public String getObservaciones(){
            return this._observaciones;
        }

        /**
         * 
         * @param o
         */
        public void setObservacioenes ( String o ){
            this._observaciones = o;
        }
	
	/**
	 * @brief Obtiene las direcciones del usuario
	 * @throws ClassNotFoundException,IOException,SQLException 
	 */
	public Direccion [] getDirecciones() throws SQLException, IOException, ClassNotFoundException {
		return Direccion.get(_idUsuario, null);
	}
	
	/**
	 * @brief Borra todas las relaciones a direcciones del usuario
	 * @throws ClassNotFoundException,IOException,SQLException 
	 */
	public void deleteDirecciones() throws SQLException, IOException, ClassNotFoundException {
		DireccionDAO.deleteDirecciones(_idUsuario);
	}
	
	/**
	 * @brief Encripta la cadena de entrada en MD5
	 * @param cadena Cadena a encriptar
	 * @return Cadena encriptada
	 * @throws NoSuchAlgorithmException
	 */
	public static String encriptarCadena(String cadena) throws NoSuchAlgorithmException {
        
		byte[] defaultBytes = cadena.getBytes();
			MessageDigest algorithm = MessageDigest.getInstance("MD5");
			algorithm.reset();
			algorithm.update(defaultBytes);
			byte messageDigest[] = algorithm.digest();
		            
			StringBuffer hexString = new StringBuffer();
			for (int i=0;i<messageDigest.length;i++) {
				hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
			}
			//String foo = messageDigest.toString();
			return hexString+"";
	}
}